<template>
  <div class="image">
    <div
      ref="canvas"
      class="zrender"
      @mousewheel="mousewheel"
      @mousedown="mousedown"
      @mousemove="mousemove"
      @mouseup="mouseup"
      @dblclick="dblclick"
    ></div>
  </div>
</template>

<script>
import { ref, onMounted } from "vue";
// import "zrender/src/canvas/canvas";
import { init, Image } from "zrender";

export default {
  setup() {
    const logo = ref("/NAMIS.png");

    const canvas = ref(null);

    const modifyCenter = () => {
      imageCenter = { x: 200, y: 200 };
      refresh();
    };

    const mousewheel = (e) => {
      if (e.wheelDelta == 120) {
        if (zoom === maxZoom) {
          return;
        }
        zoom = Math.min(zoom + 1, maxZoom);
        imageCenter.x = e.offsetX + (imageCenter.x - e.offsetX) * 2;
        imageCenter.y = e.offsetY + (imageCenter.y - e.offsetY) * 2;
      } else {
        if (zoom === minZoom) {
          return;
        }
        zoom = Math.max(zoom - 1, minZoom);
        imageCenter.x = e.offsetX + (imageCenter.x - e.offsetX) / 2;
        imageCenter.y = e.offsetY + (imageCenter.y - e.offsetY) / 2;
      }
      refresh();
    };

    let down = false;
    let startPointer = { x: 0, y: 0 };
    let startImageCenter = { x: 0, y: 0 };
    const mousedown = (e) => {
      down = true;
      startPointer = { x: e.clientX, y: e.clientY };
      startImageCenter = { x: imageCenter.x, y: imageCenter.y };
    };
    const mousemove = (e) => {
      if (down) {
        imageCenter.x = e.clientX - (startPointer.x - startImageCenter.x);
        imageCenter.y = e.clientY - (startPointer.y - startImageCenter.y);

        refresh();
      }
    };
    const mouseup = () => {
      down = false;
    };
    const dblclick = (e) => {
      if (zoom === maxZoom) {
        return;
      }
      zoom = Math.min(zoom + 1, maxZoom);
      imageCenter.x = e.offsetX + (imageCenter.x - e.offsetX) * 2;
      imageCenter.y = e.offsetY + (imageCenter.y - e.offsetY) * 2;

      refresh();
    };

    const images = {};
    const allImages = {};
    /**
     * 获取瓦片图片
     */
    const getImage = (center, tile, zoom) => {
      const id = `${zoom}_${tile.nx}_${tile.ny}`;
      if (!allImages[id]) {
        allImages[id] = new Image({
          id,
          style: {
            opacity: 1,
            image: `/C:/Users/86159/Desktop/resoult/baidumap/tiles/${zoom}/tile-${tile.nx}_${tile.ny}.png`,
            x: center.x + tile.x,
            y: center.y + tile.y,
            width: 256,
            height: 256,
          },
        });
      } else {
        allImages[id].attr({
          style: {
            opacity: 1,
            x: center.x + tile.x,
            y: center.y + tile.y,
          },
        });
      }
      return allImages[id];
    };

    /**
     * 获取瓦片
     */
    const getTiles = () => {
      // 图像移动后，图像中心与画布中心相差瓦片数量
      let tileDiff = {
        nx: Math.floor((canvasCenter.x - imageCenter.x) / 256),
        ny: -Math.floor((canvasCenter.y - imageCenter.y) / 256),
      };

      // 瓦片编号、相对中心点坐标
      let xTiles = [];
      for (
        let nx = -tileCount.nx + tileDiff.nx;
        nx <= tileCount.nx + tileDiff.nx;
        nx++
      ) {
        let yTiles = [];
        for (
          let ny = -tileCount.ny - 2 + tileDiff.ny;
          ny <= tileCount.ny + tileDiff.ny;
          ny++
        ) {
          yTiles.push({
            nx,
            ny,
            x: nx * 256 + (imageCenter.x - canvasCenter.x),
            y: ny * 256 * -1 - 256 + (imageCenter.y - canvasCenter.y),
          });
        }
        xTiles.push(yTiles);
      }
      let topTiles = xTiles.splice(0, Math.floor(xTiles.length / 2));
      xTiles = [...topTiles.reverse(), ...xTiles];
      let tiles = [];
      xTiles.forEach((yTiles) => {
        let topTiles = yTiles.splice(0, Math.floor(yTiles.length / 2));
        tiles.push(...topTiles.reverse());
        tiles.push(...yTiles);
      });

      return tiles;
    };

    /**
     * 刷新瓦片图片
     */
    const refresh = () => {
      let tiles = getTiles();

      // 渲染瓦片图片
      tiles.map((tile) => {
        const id = `${zoom}_${tile.nx}_${tile.ny}`;
        if (images[id]) {
          images[id].attr({
            style: {
              x: canvasCenter.x + tile.x,
              y: canvasCenter.y + tile.y,
            },
          });
        } else {
          images[id] = getImage(canvasCenter, tile, zoom);
          zr.add(images[id]);
          // images[id].animateFrom({
          //   style: {
          //     opacity: 0
          //   }
          // }, 300)
        }
      });
      Object.keys(images).forEach((key) => {
        if (!tiles.some((tile) => `${zoom}_${tile.nx}_${tile.ny}` === key)) {
          // images[key].animateTo({
          //   style: {
          //     opacity: 0
          //   }
          // }, 300, () => {
          zr.remove(images[key]);
          delete images[key];
          // })
        }
      });
    };

    let width = 0;
    let height = 0;

    let zoom = 8;
    let maxZoom = 8;
    let minZoom = 4;

    let imageCenter = { x: 0, y: 0 };
    let canvasCenter = { x: 0, y: 0 };

    let tileCount = { nx: 0, ny: 0 };

    let zr;

    /**
     * 初始化参数
     */
    const initPara = () => {
      zr = init(canvas.value);

      width = zr.getWidth();
      height = zr.getHeight();

      // 图像中心点实际位置
      imageCenter = {
        x: Math.round(width / 2),
        y: Math.round(height / 2),
      };
      // 画布中心点
      canvasCenter = {
        x: Math.round(width / 2),
        y: Math.round(height / 2),
      };
      // 瓦片数量
      tileCount = {
        nx: Math.floor(canvasCenter.x / 256) + 1,
        ny: Math.floor(canvasCenter.y / 256),
      };
    };

    onMounted(() => {
      initPara();
      refresh();
    });

    return {
      logo,
      canvas,
      modifyCenter,
      mousewheel,
      mousedown,
      mousemove,
      mouseup,
      dblclick,
    };
  },
};
</script>

<style>
.image {
  height: 100%;
}
.zrender {
  width: 100%;
  height: 100%;
}
</style>